package com.zsr.common.utils.oss;


import com.alibaba.fastjson2.JSONObject;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;

import com.aliyun.sts20150401.models.AssumeRoleResponse;
import com.aliyun.sts20150401.models.AssumeRoleResponseBody;
import com.aliyun.tea.TeaException;
import com.zsr.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileInputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Slf4j
@Component
public class AliCloudUtil {

    @Value("${aliyun.accessKeyId}")
    private String accessKeyId;

    @Value("${aliyun.secretAccessKey}")
    private String secretAccessKey;

    @Value("${aliyun.oss.endPoint}")
    private String endPoint;

    @Value("${aliyun.oss.bucketName}")
    private String bucketName;

    @Value("${aliyun.oss.roleArn}")
    private String roleArn;

    @Value("${aliyun.oss.roleSessionName}")
    private String roleSessionName;

    public static com.aliyun.sts20150401.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
                // 必填，您的 AccessKey ID
                .setAccessKeyId(accessKeyId)
                // 必填，您的 AccessKey Secret
                .setAccessKeySecret(accessKeySecret);
        // Endpoint 请参考 https://api.aliyun.com/product/Sts
        config.endpoint = "zsrctx.oss-cn-beijing.aliyuncs.com";
        return new com.aliyun.sts20150401.Client(config);
    }


    public AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials getStsToken() {
        // 请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
        // 工程代码泄露可能会导致 AccessKey 泄露，并威胁账号下所有资源的安全性。以下代码示例使用环境变量获取 AccessKey 的方式进行调用，仅供参考，建议使用更安全的 STS 方式，更多鉴权访问方式请参见：https://help.aliyun.com/document_detail/378657.html
        try {
            com.aliyun.sts20150401.Client client = AliCloudUtil.createClient(accessKeyId, secretAccessKey);
            com.aliyun.sts20150401.models.AssumeRoleRequest assumeRoleRequest = new com.aliyun.sts20150401.models.AssumeRoleRequest();
            com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
            // 复制代码运行请自行打印 API 的返回值
            assumeRoleRequest.setRoleArn(roleArn);
            assumeRoleRequest.setRoleSessionName(roleSessionName);
            AssumeRoleResponse assumeRoleResponse = client.assumeRoleWithOptions(assumeRoleRequest, runtime);
            return assumeRoleResponse.body.credentials;
        } catch (TeaException error) {
            // 如有需要，请打印 error
            log.error("error1=={}", error.message);
        } catch (Exception _error) {
            TeaException error = new TeaException(_error.getMessage(), _error);
            // 如有需要，请打印 error
            log.error("error2=={}", error.message);
        }
        return null;
    }

    public String uploadOneFile(MultipartFile file, String fileName) {

        // 创建OSSClient实例。
        log.info("uploadOneFile~endPoint=={},accessKeyId:{},secretAccessKey:{}", endPoint, accessKeyId, secretAccessKey);
        OSS ossClient = null;
        try {
            ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, secretAccessKey);
        } catch (Exception e) {
            log.info("uploadOneFile~error=={}", e.getMessage());
        }

        //设置文件名
        if (StringUtils.isNotEmpty(fileName)) {
            fileName = UUID.randomUUID().toString().replace("-", "")
                    + fileName;
        } else {
            fileName = UUID.randomUUID().toString().replace("-", "")
                    + file.getOriginalFilename();
        }
        log.info("uploadOneFile~fileName=={}", fileName);
        String folder = getFolderName(fileName);
        try {
            //通过该方法快速获取文件类型
            // 创建PutObject请求。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, folder + fileName, file.getInputStream());
            ObjectMetadata metadata = new ObjectMetadata();
            log.info("FilenameExtension:" + getContentType(fileName.substring(fileName.lastIndexOf("."))));
            metadata.setContentType(getContentType(fileName.substring(fileName.lastIndexOf("."))));
            putObjectRequest.setMetadata(metadata);
            putObjectRequest.setProcess("true");
            PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);
            log.info("uploadOneFile~putObjectResult=={}", JSONObject.toJSONString(putObjectResult));
            String url;
            fileName = URLEncoder.encode(fileName, "UTF-8");
            url = "https://" + bucketName + "." + endPoint + "/" + folder + fileName;
            return url;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    public String uploadOneFileFixedName(MultipartFile file, String fileName) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, secretAccessKey);
        //设置文件名
        try {
            //通过该方法快速获取文件类型
            // 创建PutObject请求。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, file.getInputStream());
            ObjectMetadata metadata = new ObjectMetadata();
            log.info("FilenameExtension:" + getContentType(fileName.substring(fileName.lastIndexOf("."))));
            metadata.setContentType(getContentType(fileName.substring(fileName.lastIndexOf("."))));
            putObjectRequest.setMetadata(metadata);
            putObjectRequest.setProcess("true");
            PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);
            log.info("uploadOneFile~putObjectResult=={}", JSONObject.toJSONString(putObjectResult));
            fileName = URLEncoder.encode(fileName, "UTF-8");
            return "https://" + bucketName + "." + endPoint + fileName;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    public String uploadXlsxFile(FileInputStream file, String fileName) {
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, secretAccessKey);
        try {
            //通过该方法快速获取文件类型
            // 创建PutObject请求。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, "excel/" + fileName, file);
            ObjectMetadata metadata = new ObjectMetadata();
            log.info("FilenameExtension:" + getContentType(fileName.substring(fileName.lastIndexOf("."))));
            metadata.setContentType(getContentType(fileName.substring(fileName.lastIndexOf("."))));
            putObjectRequest.setMetadata(metadata);
            putObjectRequest.setProcess("true");
            PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);
            log.info("uploadOneFile~putObjectResult=={}", JSONObject.toJSONString(putObjectResult));
            String url = "";
            url = "https://" + bucketName + "." + endPoint + "/" + "excel/" + fileName;
            return url;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    public static void main(String[] args) {
        String fileName = "login-background.jpg";
        System.out.println(getContentType(fileName.substring(fileName.lastIndexOf("."))));
    }


    public List<String> uploadArrayFile(MultipartFile[] files) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, secretAccessKey);
        List<String> list = new ArrayList<>();
        try {
            //设置文件名
            for (MultipartFile file : files) {
                String fileName = UUID.randomUUID().toString().replace("-", "")
                        + file.getOriginalFilename();
                String folder = getFolderName(file.getOriginalFilename());
                // 创建PutObject请求。
                PutObjectResult putObjectResult = ossClient.putObject(bucketName, folder + fileName, file.getInputStream());
                log.info("uploadArrayFile~putObjectResult=={}", JSONObject.toJSONString(putObjectResult));
                String url = "https://" + bucketName + "." + endPoint + "/" + folder + fileName;
                list.add(url);
            }
        } catch (Exception e) {
            log.info("AliCloudUtil~uploadArrayFile~e==", e);
            return null;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return list;

    }

    public String uploadLocalFile(FileInputStream file, String fileName, String folderName) {
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, secretAccessKey);
        try {
            //通过该方法快速获取文件类型
            // 创建PutObject请求。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, folderName + "/" + fileName, file);
            ObjectMetadata metadata = new ObjectMetadata();
            log.info("FilenameExtension:" + getContentType(fileName.substring(fileName.lastIndexOf("."))));
            metadata.setContentType(getContentType(fileName.substring(fileName.lastIndexOf("."))));
            putObjectRequest.setMetadata(metadata);
            putObjectRequest.setProcess("true");
            PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);
            log.info("uploadOneFile~putObjectResult=={}", JSONObject.toJSONString(putObjectResult));
            String url = "";
            url = "https://" + bucketName + "." + endPoint + "/" + folderName + "/" + fileName;
            return url;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    public boolean deleteFile(String fileUrl) {

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, secretAccessKey);
        /** oss删除文件是根据文件完成路径删除的，但文件完整路径中不能包含Bucket名称。
         * 比如文件路径为：http://edu-czf.oss-cn-guangzhou.aliyuncs.com/2022/08/abc.jpg",
         * 则完整路径就是：2022/08/abc.jpg
         */
        int begin = ("https://" + bucketName + "." + endPoint + "/").length(); //找到文件路径的开始下标
        String deleteUrl = fileUrl.substring(begin);
        try {
            // 删除文件请求
            ossClient.deleteObject(bucketName, deleteUrl);
            return true;
        } catch (Exception e) {
            log.info("AliCloudUtil~deleteFile~e==", e);
            return false;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    private String getFolderName(String originalFilename) {
        if (StringUtils.isEmpty(originalFilename)) {
            return "other/";
        }
        if (originalFilename.endsWith("gif") || originalFilename.endsWith("jpeg") || originalFilename.endsWith("jpg") || originalFilename.endsWith("png")) {
            return "img/";
        }
        if (originalFilename.endsWith("txt") || originalFilename.endsWith("pptx")
                || originalFilename.endsWith("docx") || originalFilename.endsWith("doc")
                || originalFilename.endsWith("ppt") || originalFilename.endsWith("xls")
                || originalFilename.endsWith("xlsx") || originalFilename.endsWith("pdf")) {
            return "office/";
        }
        if (originalFilename.endsWith("mp4") || originalFilename.endsWith("avi") || originalFilename.endsWith("zip")) {
            return "video/";
        }
        if (originalFilename.endsWith("stp")) {
            return "stp/";
        }

        return "other/";
    }


    public static String getContentType(String FilenameExtension) {
        if (FilenameExtension.equalsIgnoreCase(".bmp")) {
            return "image/bmp";
        }
        if (FilenameExtension.equalsIgnoreCase(".gif")) {
            return "image/gif";
        }
        if (FilenameExtension.equalsIgnoreCase(".jpeg") ||
                FilenameExtension.equalsIgnoreCase(".jpg") ||
                FilenameExtension.equalsIgnoreCase(".png")) {
            return "image/jpg";
        }
        if (FilenameExtension.equalsIgnoreCase(".html")) {
            return "text/html";
        }
        if (FilenameExtension.equalsIgnoreCase(".txt")) {
            return "text/plain";
        }
        if (FilenameExtension.equalsIgnoreCase(".vsd")) {
            return "application/vnd.visio";
        }
        if (FilenameExtension.equalsIgnoreCase(".pptx") ||
                FilenameExtension.equalsIgnoreCase(".ppt")) {
            return "application/vnd.ms-powerpoint";
        }
        if (FilenameExtension.equalsIgnoreCase(".docx") ||
                FilenameExtension.equalsIgnoreCase(".doc")) {
            return "application/msword";
        }
        if (FilenameExtension.equalsIgnoreCase(".xml")) {
            return "text/xml";
        }
        if (FilenameExtension.equalsIgnoreCase(".pdf")) {
            return "application/pdf";
        }
        return "image/jpg";
    }
}
